package com.xiaren.service;

import com.xiaren.config.DemoCacheConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Random;
import java.util.UUID;

/**
 * @Description: TODO
 * @ClassName: DemoService
 * @Auther: Administrator
 * @Date: 2018/12/14 13:53
 * @Version: 0.0.1
 */

@Slf4j
@Service
public class DemoService {

    @Autowired
    BookingService bookingService;


    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private DemoCacheConfig demoCacheConfig;

    @Autowired
    DemoService2 demoService2;


    @Transactional
    public void demoAdd(){
        System.out.println("模式事务提交");

        rabbitTemplate.convertAndSend("乱七八糟测试");
    }


    public void demoRabbitMQ(){
        log.info("无事务提交模式");
        rabbitTemplate.convertAndSend("乱七八糟测试");
    }

    /**
     * 模拟缓存适配spring事务
     */
    @Transactional
    public void demoCacheTransaction(){

        demoCacheConfig.put("tran-key", "测试value");
    }

    @Transactional
    public void demoCacheTransaction2(){
        demoCacheConfig.putError("tran-key", "测试value");
    }

    @Transactional
    public void demoCacheTransactionError(){
        bookingService.book("abc");
        demoCacheConfig.putError("tran-key", "测试value");
    }


    /**
     * 测试事务回滚
     */
    @Transactional
    public void demoTransactionRollBack(){
        bookingService.book("abc1");

        System.out.println(1/0);
    }

    /**
     * 多线程情况下
     */
    @Transactional
    public void demoMultithreading(){

        bookingService.book("be");

        new Thread(() -> {
            // 线程中的测试
            bookingService.book("xx");

            // 线程中报错的测试
            bookingService.book("我是报错111111111111111");
        }).start();


        // 名字超过5个字符则报错
        bookingService.book("bb");
    }



    public void simulationRabbitMQ(){
        bookingService.book("111");
        new Thread(() -> {
            rabbitMQListener();
        }).start();
        bookingService.book("111错误错误错误");
    }

    public void simulationRabbitMQ2(){
        bookingService.book("111");
        new Thread(){
            @Override
            public void run() {
                rabbitMQListener();
            }

            {
                setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {  // 多线程状态下的手动回滚
                    public void uncaughtException(Thread t, Throwable e) {
                        try {
                            bookingService.deleteByName("mq11", "mq错误错误");
                        } catch (Exception e1) {
                            e1.printStackTrace();
                        }
                    }
                });
            }
        }.start();
        bookingService.book("111错误错误错误");
    }

    @Transactional
    public void rabbitMQListener(){
        bookingService.book("mq11");

        bookingService.book("mq错误错误");
    }


    // 测试普通mysql事务, 内部有本类事务
    public void transactionMySqlDemo(){
        bookingService.book("111");
        bookingService.book("222");
        transactionMySqlDemo2();
    }


    // 本类中的事务调用
    @Transactional
    public void transactionMySqlDemo2(){
        System.out.println("xxxxxxxx 完结");
        bookingService.book("333");
        bookingService.book("555555555555555555555错误");
    }

    public void transactionMySqlDemoOther(){
        bookingService.book("111");
        bookingService.book("222");
        demoService2.transactionMySqlDemo();
    }




}
